from django.shortcuts import render, redirect, HttpResponse
from django.http.response import JsonResponse
from web import models
from django.urls import reverse
from web.Forms.file import FolderModelForm, FileModelForm
# 字典对象
from django.forms.models import model_to_dict
from utils.tencent.cos import delete_file, delete_file_obj, credential, check_file
from django.views.decorators.csrf import csrf_exempt
import json
import requests

'''
文件
'''


def file(request, project_id):
    # http://127.0.0.1:8000/manage/17/file/  根文件夹
    # http://127.0.0.1:8000/manage/17/file/?folder=7  子文件夹
    '''文件夹管理 文件夹添加'''
    parent_obj = None
    folder_id = request.GET.get('folder', '')
    # 查出当前对象 给前端渲染 循环
    if folder_id.isdecimal():
        parent_obj = models.FileRepository.objects.filter(id=int(folder_id), project=request.tracer.project,
                                                          file_type=2).first()
    if request.method == 'GET':
        # 文件导航导航
        breadcrumb_list = []
        parent = parent_obj
        while parent:
            breadcrumb_list.insert(0, model_to_dict(parent, ['id', 'name']))
            # breadcrumb_list.insert(0, {'id': parent.id, 'name': parent.name})
            parent = parent.parent

        # 文件展示
        queryset = models.FileRepository.objects.filter(project=request.tracer.project)
        if parent_obj:
            # 进入了目录 一直渲染 file_object_list 文件列表对象
            file_object_list = queryset.filter(parent=parent_obj).order_by('-file_type')
        else:
            # 根目录
            file_object_list = queryset.filter(parent__isnull=True)

        form = FolderModelForm(request, parent_obj)
        return render(request, 'file.html', locals())
    # post
    fid = request.POST.get('fid', '')
    edit_object = None
    if fid.isdecimal():
        edit_object = models.FileRepository.objects.filter(id=int(fid), project=request.tracer.project,
                                                           file_type=2
                                                           ).first()
    if edit_object:
        # 编辑
        form = FolderModelForm(request, parent_obj, data=request.POST, instance=edit_object)
        # form = FolderModelForm(request, parent_obj, data=request.POST)  这样的话一直走的就是form新增
    else:
        form = FolderModelForm(request, parent_obj, data=request.POST)
    if form.is_valid():
        form.instance.file_type = 2
        form.instance.update_user = request.tracer.user
        form.instance.project = request.tracer.project
        form.instance.parent = parent_obj
        form.save()
        return JsonResponse({'status': 1})
    return JsonResponse({'status': 0, 'msg': form.errors})


def file_delete(request, project_id):
    '''删除文件'''
    fid = request.GET.get('fid', '')
    delete_object = models.FileRepository.objects.filter(id=fid, project=request.tracer.project).first()
    if delete_object.file_type == 1:
        # 文件删除，项目使用空间返回 数据库删除  cos删除
        # 项目使用空间返回  # 默认字节
        request.tracer.project.user_space -= delete_object.file_size
        request.tracer.project.save()
        # 数据库删除
        delete_object.delete()
        # cos删除
        delete_file(Bucket=request.tracer.project.bucket, region=request.tracer.project.region,
                    Key=delete_object.key)
        return JsonResponse({'status': True})

    else:
        # 文件夹删除
        total_size = 0
        # folder_list 全是文件夹
        folder_list = [delete_object, ]
        # 文件对象
        key_list = []
        for folder in folder_list:
            # 从底层找父级 这样可以找到所有文件夹以及文件
            child_list = models.FileRepository.objects.filter(project=request.tracer.project, parent=folder).order_by(
                '-file_type')
            for child in child_list:
                if child.file_type == 2:
                    folder_list.append(child)
                else:
                    # 文件大小
                    total_size += child.file_size
                    # 当前文件对象
                    key_list.append({'Key': child.key})
        if total_size:
            # 归还空间
            request.tracer.project.user_space -= total_size
            request.tracer.project.save()
        if key_list:
            # cos批量删除
            delete_file_obj(Bucket=request.tracer.project.bucket, region=request.tracer.project.region,
                            Key=key_list)
        # 数据库删除
        delete_object.delete()

    return JsonResponse({'status': 1})


@csrf_exempt
def cos_credential(request, project_id):
    """ 获取cos上传临时凭证 """
    # 单文件限制
    per_file_limit = request.tracer.price_policy.project_size * 1024 * 1024
    total_file_limit = request.tracer.price_policy.project_space * 1024 * 1024 * 1024

    total_size = 0
    file_list = json.loads(request.body.decode('utf-8'))
    for item in file_list:
        # 文件的字节大小 item['size'] = B
        # 单文件限制的大小 M
        # 超出限制
        if item['size'] > per_file_limit:
            msg = "单文件超出限制（最大{}M），文件：{}，请升级套餐。".format(request.tracer.price_policy.project_size, item['name'])
            return JsonResponse({'status': False, 'error': msg})
        total_size += item['size']

        # 做容量限制：单文件 & 总容量

    # 总容量进行限制
    # request.tracer.price_policy.project_space  # 项目的允许的空间
    # request.tracer.project.use_space # 项目已使用的空间
    # 项目的使用空间+上传文件空间
    if request.tracer.project.user_space + total_size > total_file_limit:
        return JsonResponse({'status': False, 'error': "容量超过限制，请升级套餐。"})
    # 获取cos上传临时凭证
    data_dict = credential(request.tracer.project.bucket, request.tracer.project.region)
    return JsonResponse({'status': True, 'data': data_dict})


@csrf_exempt
def file_post(request, project_id):
    """ 已上传成功的文件写入到数据 """
    """
    name: fileName,
    key: key,
    file_size: fileSize,
    parent: CURRENT_FOLDER_ID,
    # etag: data.ETag,
    file_path: data.Location
    """
    # 根据key再去cos获取文件Etag和"db7c0d83e50474f934fd4ddf059406e5"

    # print(request.POST)
    # 把获取到的数据写入数据库即可
    form = FileModelForm(request, data=request.POST)

    if form.is_valid():
        # 通过ModelForm.save存储到数据库中的数据返回的isntance对象，无法通过get_xx_display获取choice的中文
        # form.instance.file_type = 1
        # form.update_user = request.tracer.user
        # instance = form.save() # 添加成功之后，获取到新添加的那个对象（instance.id,instance.name,instance.file_type,instace.get_file_type_display()

        # 校验通过：数据写入到数据库
        data_dict = form.cleaned_data
        data_dict.pop('etag')
        data_dict.update({'project': request.tracer.project, 'file_type': 1,
                          'update_user': request.tracer.user})
        instance = models.FileRepository.objects.create(**data_dict)

        # 项目的已使用空间：更新 (data_dict['file_size'])
        request.tracer.project.user_space += data_dict['file_size']
        request.tracer.project.save()

        result = {
            'id': instance.id,
            'name': instance.name,
            'file_size': instance.file_size,
            'username': instance.update_user.username,
            'datetime': instance.update_datetime,
            # 'download_url': reverse('file_download', kwargs={"project_id": project_id, 'file_id': instance.id})
            # 'file_type': instance.get_file_type_display()
        }
        return JsonResponse({'status': True, 'data': result})

    return JsonResponse({'status': False, 'data': "文件错误"})


def file_download(request, project_id, file_id):
    '''下载文件'''
    file_obj = models.FileRepository.objects.filter(project_id=project_id, id=file_id).first()
    url = file_obj.file_path
    # 大文件的下载
    data = requests.get(url).iter_content()
    # 正常文件的下载
    # data = requests.get(url).content
    # 弹框提示框
    response = HttpResponse(data, content_type="application/octet-stream")
    # 中文转义
    from django.utils.encoding import escape_uri_path
    # 设置下载头
    response['Content-Disposition'] = "attachment; filename={};".format(escape_uri_path(file_obj.name))
    return response
